﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// SetPasswordPanel.xaml 的交互逻辑
    /// </summary>
    public partial class SetPasswordPanel : UserControl
    {
        /// <summary>
        /// [构造方法]创建一个密码输入面板。
        /// 此面板被嵌入在 MarkdownEditor中，并覆盖在 EditorBase 表层。
        /// 平时此面板总是隐藏着的，当需要加密文件时才会出现。
        /// 如果文档被加密，则在输入正确的密码前，
        /// 此面板会遮挡住 EditorBase，从而无法察看、编辑文本。
        /// </summary>
        /// <param name="masterEditor">寄宿于哪个编辑器。</param>
        public SetPasswordPanel(MarkdownEditor masterEditor)
        {
            InitializeComponent();

            this.masterEditor = masterEditor;
        }

        /// <summary>
        /// 寄宿的编辑器。
        /// </summary>
        private MarkdownEditor masterEditor;

        /// <summary>
        /// [简单加密方法]将指定文本转换为字符数组。
        /// </summary>
        /// <param name="content">要加密的文本。</param>
        /// <param name="secretKey">安全密钥文本。</param>
        /// <returns>返回字符数组。</returns>
        public static char[] TextEncrypt(string content, string secretKey)
        {
            char[] data = content.ToCharArray();
            char[] key = secretKey.ToCharArray();
            for (int i = 0; i < data.Length; i++)
            {
                data[i] ^= key[i % key.Length];
            }
            return data;
        }

        /// <summary>
        /// [简单解密方法]将加密后的字符数组还原为文本。
        /// </summary>
        /// <param name="data">加密后的字符数组。</param>
        /// <param name="secretKey">安全密钥文本。</param>
        /// <returns>返回加密前的文本。</returns>
        public static string TextDecrypt(char[] data, string secretKey)
        {
            char[] key = secretKey.ToCharArray();
            for (int i = 0; i < data.Length; i++)
            {
                data[i] ^= key[i % key.Length];
            }
            return new string(data);
        }

        /// <summary>
        /// 加密文件。
        /// </summary>
        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            EncryptFile();
        }

        /// <summary>
        /// 加密主编辑器中的文本。
        /// </summary>
        private void EncryptFile()
        {
            if (string.IsNullOrWhiteSpace(tbxQuestion.Text))
            {
                LMessageBox.Show("　　密码提示文本不能是空白字符（或字符串）！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (tbxPassword.Password != tbxPassword2.Password)
            {
                LMessageBox.Show("　　两次输入的密码不一致！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                tbxPassword.Focus();
                return;
            }

            var encryptedText = new String(TextEncrypt(this.masterEditor.EditorBase.Document.Text, "DyBj#PpBb"));
            var fstLine = new String(TextEncrypt($"Question:{tbxQuestion.Text}|Password:{tbxPassword.Password}", "DyBj#PpBb")).Replace("\r", "[[<r>]]").Replace("\n", "[[<n>]]");

            File.WriteAllText(this.masterEditor.FullFilePath, $"{fstLine}\r\n{new String(SetPasswordPanel.TextEncrypt(this.masterEditor.EditorBase.Document.Text, "DyBj#PpBb"))}");
            this.masterEditor.Password = tbxPassword.Password;
            this.masterEditor.PasswordTip = tbxQuestion.Text;
            this.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// 放弃加密文档，隐藏此面板。
        /// </summary>
        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// 加密文件。
        /// </summary>
        private void tbxPassword_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                EncryptFile();
            }
        }

        /// <summary>
        /// 加密文件。
        /// </summary>
        private void tbxPassword2_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                EncryptFile();
            }
        }
    }
}
